home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Atari Mega Archive 1
/
Atari Mega Archive - Volume 1.iso
/
telecomm
/
sticpsrc.lzh
/
SOURCE.ARC
/
SMTPCLI.C
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-10
|
26KB
|
1,099 lines
/*
* Client routines for Simple Mail Transfer Protocol ala RFC821
* A.D. Barksdale Garbee II, aka Bdale, N3EUA
* Copyright 1986 Bdale Garbee, All Rights Reserved.
* Permission granted for non-commercial copying and use, provided
* this notice is retained.
* Modified 14 June 1987 by P. Karn for symbolic target addresses,
* also rebuilt locking mechanism
* Limit on max simultaneous sessions, reuse of connections - 12/87 NN2Z
* Added return of mail to sender as well as batching of commands 1/88 nn2z
*/
#include <stdio.h>
#ifndef ATARI_ST
#include <fcntl.h>
#endif
#include <time.h>
#ifdef UNIX
#include <sys/types.h>
#endif
#include "global.h"
#include "config.h"
#include "netuser.h"
#include "mbuf.h"
#include "timer.h"
#include "tcp.h"
#include "smtp.h"
#include "trace.h"
#include "cmdparse.h"
extern int16 lport; /* local port */
extern int32 resolve();
static struct timer smtpcli_t; /* client startup timer */
static int32 queuetime = SEC2TICK(500); /* kicktime for queued mail */
int32 gateway;
#ifdef SMTPTRACE
int16 smtptrace = 0; /* used for trace level */
int dosmtptrace();
#endif
int16 smtpmaxcli = MAXSESSIONS; /* the max client connections allowed */
int16 smtpsessions = 0; /* number of client connections
* currently open */
int16 smtpmode = 0;
static struct smtp_cb *cli_session[MAXSESSIONS]; /* queue of client sessions */
static char helocmd[] = "HELO %s\r\nMAIL FROM:<%s>\r\n";
static char mailcmd[] = "MAIL FROM:<%s>\r\n";
static char rcptcmd[] = "RCPT TO:<%s>\r\n";
static char datacmd[] = "DATA\r\n";
static char rsetcmd[] = "RSET\r\n";
static char quitcmd[] = "QUIT\r\n";
static char eom[] = "\r\n.\r\n";
static int smtptick(),dogateway(),dosmtpmaxcli(),dotimer();
static int setsmtpmode(),sendwindow();
static void quit(),abort_trans(),sendit(),del_job();
static void execjobs(),smtp_transaction();
static struct smtp_cb *newcb(),*lookup();
static struct smtp_job *setupjob();
void del_session(),logerr(),retmail();
int mlock(),rmlock(),nextjob();
extern void mbxfwd();
extern char *getnenv();
#if (defined(ATARI_ST) && defined(__TURBOC__))
static void sendit(struct smtp_cb *,char *,...);
#endif
struct cmds smtpcmds[] = {
"gateway", dogateway, 0, NULLCHAR, NULLCHAR,
"mode", setsmtpmode, 0, NULLCHAR, NULLCHAR,
"kick", smtptick, 0, NULLCHAR, NULLCHAR,
"maxclients", dosmtpmaxcli, 0, NULLCHAR, NULLCHAR,
"timer", dotimer, 0, NULLCHAR, NULLCHAR,
#ifdef SMTPTRACE
"trace", dosmtptrace, 0, NULLCHAR, NULLCHAR,
#endif
NULLCHAR, NULLFP, 0,
"?subcommands",
NULLCHAR
};
dosmtp(argc,argv)
int argc;
char *argv[];
{
return subcmd(smtpcmds,argc,argv);
}
static int
dosmtpmaxcli(argc,argv)
int argc;
char *argv[];
{
int x;
if (argc < 2)
printf("%d\n",smtpmaxcli);
else {
x = atoi(argv[1]);
if (x > MAXSESSIONS)
printf("max clients must be <= %d\n",MAXSESSIONS);
else
smtpmaxcli = x;
}
return 0;
}
static int
setsmtpmode(argc,argv)
int argc;
char *argv[];
{
if (argc < 2) {
printf("smtp mode: %s\n",
(smtpmode & QUEUE) ? "queue" : "route");
} else {
switch(*argv[1]) {
case 'q':
smtpmode |= QUEUE;
break;
case 'r':
smtpmode &= ~QUEUE;
break;
default:
printf("Usage: smtp mode [queue | route]\n");
break;
}
}
return 0;
}
static int
dogateway(argc,argv)
int argc;
char *argv[];
{
extern char badhost[];
if(argc < 2){
printf("%s\n",inet_ntoa(gateway));
} else if((gateway = resolve(argv[1])) == 0 && argv[1][0] != '['){
printf(badhost,argv[1]);
return 1;
}
return 0;
}
#ifdef SMTPTRACE
static int
dosmtptrace(argc,argv)
int argc;
char *argv[];
{
if (argc < 2)
printf("%d\n",smtptrace);
else
smtptrace = atoi(argv[1]);
return 0;
}
#endif
/* Set outbound spool poll interval */
static int
dotimer(argc,argv)
int argc;
char *argv[];
{
if(argc < 2){
printf("%lu/%lu (%lu)\n",TICK2SEC(smtpcli_t.start - smtpcli_t.count),
TICK2SEC(smtpcli_t.start),
TICK2SEC(queuetime));
return 0;
}
stop_timer(&smtpcli_t);
smtpcli_t.func = (void (*)())smtptick; /* what to call on timeout */
smtpcli_t.start = SEC2TICK(atol(argv[1])); /* set timer duration */
start_timer(&smtpcli_t); /* and fire it up */
if (argc > 2) /* queuetime specified? */
queuetime = SEC2TICK(atol(argv[2]));
return 0;
}
/* kick the timer when a job is queued */
void
queuekick()
{
int32 savedstart;
if (queuetime == 0) /* no queue'd job kick? */
return;
savedstart = smtpcli_t.start; /* keep normal smtp timer */
stop_timer(&smtpcli_t);
smtpcli_t.func = (void (*)())smtptick;
smtpcli_t.start = queuetime; /* set temporary timer value */
start_timer(&smtpcli_t); /* and fire it up */
smtpcli_t.start = savedstart; /* restore full time value */
}
/* this is the routine that gets called every so often to do outgoing mail
processing */
static int
smtptick()
{
register struct smtp_cb *cb;
struct smtp_job *jp;
#ifdef SMTPTRACE
struct list *ap;
#endif
char *mailqdir;
char *cp, *cp1;
int32 destaddr;
FILE *wfile;
char sysname[LINELEN], tmpstring[LINELEN];
char wfilename[13], prefix[9];
char mailq[80];
#ifdef SMTPTRACE
if (smtptrace > 5) {
printf("smtp daemon entered\n");
fflush(stdout);
}
#endif
strcpy(mailq,mailqdir = getnenv(MAILQDIR));
strcat(mailq,mailqueue);
for(filedir(mailq,0,wfilename);wfilename[0] != '\0';
filedir(mailq,1,wfilename)){
/* save the prefix of the file name which it job id */
cp = wfilename;
cp1 = prefix;
while (*cp && *cp != '.')
*cp1++ = *cp++;
*cp1 = '\0';
/* lock this file from the smtp daemon */
if (mlock(mailqdir,prefix))
continue;
sprintf(tmpstring,"%s%s",mailqdir,wfilename);
if ((wfile = fopen(tmpstring,"r")) == NULLFILE) {
/* probably too many open files */
rmlock(mailqdir,prefix);
/* continue to next message. The failure
* may be temporary */
continue;
}
fgets(sysname,LINELEN,wfile); /* read target host */
rip(sysname);
if ((destaddr = mailroute(sysname)) == 0) {
fclose(wfile);
printf("** smtp: Unknown address %s\n",sysname);
fflush(stdout);
continue;
}
if ((cb = lookup(destaddr)) == NULLCB) {
/* there are enough processes running already */
if (smtpsessions >= smtpmaxcli) {
#ifdef SMTPTRACE
if (smtptrace) {
printf("smtp daemon: too many processes\n");
fflush(stdout);
}
#endif
fclose(wfile);
rmlock(mailqdir,prefix);
continue;
}
if ((cb = newcb(tmpstring)) == NULLCB) {
fclose(wfile);
rmlock(mailqdir,prefix);
continue;
}
cb->ipdest = destaddr;
} else {
/* This system already is sending mail lets not
* interfere with it's send queue.
*/
if (cb->state != CLI_INIT_STATE && cb->state != CLI_OPEN_STATE) {
fclose(wfile);
rmlock(mailqdir,prefix);
continue;
}
}
fgets(tmpstring,LINELEN,wfile); /* read from */
rip(tmpstring);
if ((jp = setupjob(cb,prefix,sysname,tmpstring)) == NULLJOB) {
fclose(wfile);
rmlock(mailqdir,prefix);
del_session(cb);
continue;
}
while (fgets(tmpstring,LINELEN,wfile) != NULLCHAR) {
rip(tmpstring);
if (addlist(&jp->to,tmpstring,DOMAIN) == NULLLIST) {
fclose(wfile);
del_session(cb);
}
}
fclose(wfile);
#ifdef SMTPTRACE
if (smtptrace > 1) {
printf("queue job %s From: %s To:",prefix,from);
for (ap = jp->to; ap != NULLLIST; ap = ap->next)
printf(" %s",ap->val);
printf("\n");
fflush(stdout);
}
#endif
}
/* start sending that mail */
execjobs();
/* Restart timer */
start_timer(&smtpcli_t);
}
/* this is the master state machine that handles a single SMTP transaction */
static void
smtp_transaction(cb)
register struct smtp_cb *cb;
{
void smtp_cts();
register char reply;
register struct list *tp;
int cnt;
struct mbuf *bp,*bpl;
char tbuf[LINELEN];
int rcode;
#ifdef SMTPTRACE
if (smtptrace > 5)
printf("smtp_transaction() enter state=%u\n",cb->state);
if (s